package com.sfc.spiderweb.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import com.csvreader.CsvReader;

/**
 * file tool
 *
 * @author zhenwei.li 2017-12-29 17:56:48
 */
public class FileUtil {
    private static Logger logger = LoggerFactory.getLogger(FileUtil.class);

    /**
     * delete recursively
     *
     * @param root
     * @return
     */
    public static boolean deleteRecursively(File root) {
        if (root != null && root.exists()) {
            if (root.isDirectory()) {
                File[] children = root.listFiles();
                if (children != null) {
                    for (File child : children) {
                        deleteRecursively(child);
                    }
                }
            }
            return root.delete();
        }
        return false;
    }

    public static void deleteFile(String fileName) {
        // file
        File file = new File(fileName);
        if (file.exists()) {
            file.delete();
        }
    }

    public static File createFile(String path) throws Exception {
        File file = new File(path);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        if (!file.exists()) {
            file.createNewFile();
        }
        return file;
    }

    /**
     * 清空文件夹下的所有内容
     *
     * @param path
     * @return
     */
    public static void deleteAll(String path) {
        File file = new File(path);
        //判断是否待删除目录是否存在
        if (!file.exists()) {
            file.mkdirs();
        }
        //取得当前目录下所有文件和文件夹
        String[] content = file.list();
        for (String name : content) {
            File temp = new File(path, name);
            //判断是否是目录
            if (temp.isDirectory()) {
                //递归调用，删除目录里的内容
                deleteDir(temp.getAbsolutePath());
                temp.delete();//删除空目录
            } else {
                //直接删除文件
                if (!temp.delete()) {
                    logger.info("Failed to delete " + name);
                }
            }
        }
    }

    public static List<List<String>> readJpCsv(String fileName) throws Exception {
        return readCsv(fileName, ',', "Shift_JIS");
    }

    public static List<List<String>> readCsv(String fileName) throws Exception {
        return readCsv(fileName, ',', "UTF-8");
    }

    public static List<List<String>> readCsv(String fileName, char c, String code) throws Exception {
        List<List<String>> result = new ArrayList<>();
        FileInputStream inputStream = new FileInputStream(fileName);
        CsvReader csvReader = new CsvReader(inputStream, c, Charset.forName(code));
        csvReader.setSafetySwitch(false);
        while (csvReader.readRecord()) {
            List<String> list = new ArrayList<>();
            for (int i = 0; i < csvReader.getColumnCount(); i++) {
                list.add(csvReader.get(i));
            }
            result.add(list);
        }
        csvReader.close();
        inputStream.close();
        return result;
    }

    /**
     * 迭代删除文件夹
     *
     * @param dirPath 文件夹路径
     */
    public static void deleteDir(String dirPath) {
        File file = new File(dirPath);
        if (file.exists()) {
            if (file.isFile()) {
                file.delete();
            } else {
                File[] files = file.listFiles();
                if (files == null) {
                    file.delete();
                } else {
                    for (int i = 0; i < files.length; i++) {
                        deleteDir(files[i].getAbsolutePath());
                    }
                    file.delete();
                }
            }
        }
    }

    public static void appendFileLine(String fileName, String content) {

        // file
        File file = new File(fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                return;
            }
        }

        // content
        if (content == null) {
            content = "";
        }
        content += "\r\n";

        // append file content
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file, true);
            fos.write(content.getBytes("utf-8"));
            fos.flush();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }

    }

    /**
     * 判断文件是否在被写入
     *
     * @return
     */
    public static boolean isFileWriting(String filePath) {
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            if (file.renameTo(file)) {
                logger.error("文件未被操作");
                return false;
            } else {
                logger.error("文件正在下载");
                return true;
            }
        } else {
            return false;
        }
    }

    public static List<String> loadFileLines(String fileName) {
        return loadFileLines(fileName, 0);
    }

    public static String loadFile(String fileName) {
        StringBuffer sb = new StringBuffer();
        List<String> list = loadFileLines(fileName);
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
            if (i != list.size() - 1) {
                sb.append("\n");
            }
        }
        return sb.toString();
    }

    public static List<String> loadFileLines(String fileName, int toLineNum) {

        List<String> result = new ArrayList<>();

        // valid log file
        File file = new File(fileName);
        if (!file.exists()) {
            return result;
        }

        // read file
        StringBuffer logContentBuffer = new StringBuffer();
        LineNumberReader reader = null;
        try {
            //reader = new LineNumberReader(new FileReader(logFile));
            reader = new LineNumberReader(new InputStreamReader(new FileInputStream(file), "GBK"));
            String line = null;
            int index = 0;
            while ((line = reader.readLine()) != null) {
                if (line != null && line.trim().length() > 0) {
                    if (index >= toLineNum) {
                        result.add(line);
                    }
                    index++;
                }
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }

        return result;
    }

    public static void mkdirParentFolder(String path) {
        File file = new File(path);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) parentFile.mkdirs();
    }

    /**
     * 文件复制
     *
     * @param srcPath    源文件路径
     * @param targetPath 复制后存放路径
     * @throws Exception
     */
    public static void copyFile(String srcPath, String targetPath) throws Exception {
        File srcFile = new File(srcPath);
        File target = new File(targetPath);
        if (!srcFile.exists()) {
            throw new Exception("文件不存在！");
        }
        if (!srcFile.isFile()) {
            throw new Exception("不是文件！");
        }
        //判断目标路径是否是目录
        if (target.isFile()) {
            throw new Exception("文件路径不存在！");
        }

        // 获取源文件的文件名
        String fileName = srcPath.substring(srcPath.lastIndexOf("\\") + 1);
        //TODO:判断是否存在相同的文件名的文件
        File[] listFiles = target.listFiles();
        for (File file : listFiles) {
            if (fileName.equals(file.getName())) {
                fileName += "_1";
            }
        }
        String newFileName = targetPath + File.separator + fileName;
        File targetFile = new File(newFileName);
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(targetFile);
            //从in中批量读取字节，放入到buf这个字节数组中，
            // 从第0个位置开始放，最多放buf.length个 返回的是读到的字节的个数
            byte[] buf = new byte[8 * 1024];
            int len = 0;
            while ((len = in.read(buf)) != -1) {
                out.write(buf, 0, len);
                out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e) {
                System.out.println("关闭输入流错误！");
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                System.out.println("关闭输出流错误！");
            }
        }

    }

    /**
     * 写txt
     *
     * @param fileName
     * @param data
     */
    public static void writeTxtAsUtf8(String fileName, String data) {
        try {
            File file = new File(fileName);
            // 创建新文件
            file.getParentFile().mkdirs();
            if (!file.exists()) file.createNewFile();
            BufferedWriter writer;
            FileOutputStream writerStream = new FileOutputStream(file);
            writer = new BufferedWriter(new OutputStreamWriter(writerStream, "UTF-8"));
            writer.write(data);
            // \r\n即为换行
            // 把缓存区内容压入文件
            writer.flush();
            // 最后记得关闭文件
            writer.close();
            logger.info("写TXT文件成功");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("写TXT文件失败");
        }
    }

    public static String readTxt(File file) {
        StringBuilder result = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
            String s;
            while ((s = br.readLine()) != null) {//使用readLine方法，一次读一行
                result.append(System.lineSeparator() + s);
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    /**
     * 第二种读取方式，避免乱码
     *
     * @param file
     * @param type
     * @return
     */
    public static String readTxt(File file, Integer type) {
        StringBuilder content = new StringBuilder("");
        try {
            String code = resolveCode(file.getAbsolutePath());
            InputStream is = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(is, code);
            BufferedReader br = new BufferedReader(isr);
            String str = "";
            while (null != (str = br.readLine())) {
                content.append(str);
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("读取文件:" + file.getAbsolutePath() + "失败!");
        }
        return content.toString();

    }

    public static String resolveCode(String path) throws Exception {
        InputStream inputStream = new FileInputStream(path);
        byte[] head = new byte[3];
        inputStream.read(head);
        String code = "gb2312";  //或GBK
        if (head[0] == -1 && head[1] == -2)
            code = "UTF-16";
        else if (head[0] == -2 && head[1] == -1)
            code = "Unicode";
        else if (head[0] == -17 && head[1] == -69 && head[2] == -65)
            code = "UTF-8";
        inputStream.close();
        logger.info(code);
        return code;
    }
}
